using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

using Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.Common;
using Microsoft.ConnectionEngine.Common.Security;
using Microsoft.ConnectionEngine.Administration.Core.ServiceProvider;
using Microsoft.ConnectionEngine.Common;

namespace Microsoft.ConnectionEngine.Administration.Core.ServiceProvider.Business
{
    public class AdapterHelper
    {
        private static SystemAdapterWS.ConnectionEngineAdapter adapter;

        internal static SystemAdapterWS.ConnectionEngineAdapter SystemAdapter
        {
            get
            {
                if (adapter == null)
                    adapter = new SystemAdapterWS.ConnectionEngineAdapter();
                return adapter;
            }
        }

        internal static ConnectionEngineMessage SendConnectionEngineMessage(int messagetypeID, string destinationID, string payload)
        {
            SystemAdapterWS.ConnectionEngineMessage result = SystemAdapter.SendConnectionEngineMessage(payload, messagetypeID, Guid.Empty, destinationID);
            //Make sure that only Common.ConnectionEngineMessage is used. Convert the WS Message type to Common Message type.
            return ConvertWSMessageToCommonMessage(result);
        }

        private static ConnectionEngineMessage ConvertWSMessageToCommonMessage(SystemAdapterWS.ConnectionEngineMessage wsmessage)
        {
            ConnectionEngineMessage result = new ConnectionEngineMessage();
            result.Header = new ConnectionEngineMessageHeader();

            result.Header.Conversation = new ConnectionEngineConversation();
            result.Header.Conversation.ConversationID = wsmessage.Header.Conversation.ConversationID;
            result.Header.Conversation.OriginalMessageID = wsmessage.Header.Conversation.OriginalMessageID;

            result.Header.CreationTime = wsmessage.Header.CreationTime;
            result.Header.ID = wsmessage.Header.ID;
            result.Header.InteractionClass = wsmessage.Header.InteractionClass;
            result.Header.InteractionType = wsmessage.Header.InteractionType;

            result.Header.Receiver = new ConnectionEngineEndPoint();
            result.Header.Receiver.ConnectionEngineUserID = wsmessage.Header.Receiver.ConnectionEngineUserID;
            result.Header.Receiver.OrganisationID = wsmessage.Header.Receiver.OrganisationID;
            result.Header.Receiver.OrganisationUserID = wsmessage.Header.Receiver.OrganisationUserID;
            result.Header.Receiver.URI = wsmessage.Header.Receiver.URI;

            result.Header.Sender = new ConnectionEngineEndPoint();
            result.Header.Sender.ConnectionEngineUserID = wsmessage.Header.Sender.ConnectionEngineUserID;
            result.Header.Sender.OrganisationID = wsmessage.Header.Sender.OrganisationID;
            result.Header.Sender.OrganisationUserID = wsmessage.Header.Sender.OrganisationUserID;
            result.Header.Sender.URI = wsmessage.Header.Sender.URI;

            result.Header.SessionToken = wsmessage.Header.SessionToken;

            result.Header.Status = new ConnectionEngineStatus();
            result.Header.Status.Code = wsmessage.Header.Status.Code;
            result.Header.Status.Description = wsmessage.Header.Status.Description;
            result.Header.Status.Details = wsmessage.Header.Status.Details;

            result.Body.Payload = new ConnectionEnginePayload();
            result.Body.Payload.Content = wsmessage.Body.Payload.Content;
            string enctype = wsmessage.Body.Payload.EncryptionType.ToString();
            result.Body.Payload.EncryptionType = (Microsoft.ConnectionEngine.Common.CryptoTypes)Utilities.StringToEnum(typeof(Microsoft.ConnectionEngine.Adapters.ConnectionEngineAdapter.CryptoTypes), enctype);
            result.Body.Payload.IV = wsmessage.Body.Payload.IV;
            result.Body.Payload.Key = wsmessage.Body.Payload.Key;

            return result;
        }

        internal static object GetPayloadObjectFromResponse(ConnectionEngineMessage response, Type type)
        {
            // Can't checkout 
            if (response.Header.Status.Code == 9)
                return null;

            if (response.Header.Status.Code != 0)
                throw new Exception(response.Header.Status.Description);

            if (response.Body.Payload.Content != string.Empty)
                return Common.Utilities.DeserializeObject(response.Body.Payload.Content, type);

            else
                return null;
        }

        internal static bool GetBooleanFromResponse(ConnectionEngineMessage response)
        {
            // Can't checkout 
            if (response.Header.Status.Code == 9)
                return false;

            if (response.Header.Status.Code != 0)
                throw new Exception(response.Header.Status.Description);

            return true;
        }
        
        
        public static string Serialise(object content, Type contentType)
        {
            System.Text.StringBuilder doc = new System.Text.StringBuilder();

            XmlSerializer serializer = new XmlSerializer(contentType);
            System.IO.TextWriter tw = new System.IO.StringWriter(doc);
            serializer.Serialize(tw, content);
            tw.Close();
            return doc.ToString();
        }

        public static string ConstructPayloadXml(HSDPrincipal principal, string rootElement, string content)
        {
            string payload = 
                String.Format(@"<request xmlns=""http://Microsoft.ConnectionEngine/Schemas/ServiceProviderRegister"">{0}<{1}>{2}</{1}></request>",
                SecurityManager.ConstructUserCredentialsXml(principal), rootElement, content);
            return payload;
        }

        public static string ConstructPayloadXml(HSDPrincipal principal, string content)
        {
            string payload =
                String.Format(@"<request xmlns=""http://Microsoft.ConnectionEngine/Schemas/ServiceProviderRegister"">{0}{1}</request>",
                SecurityManager.ConstructUserCredentialsXml(principal), content);
            return payload;
        }

        public static int GetMessageTypeValue(MessageTypes messageType)
        {
            return (int) messageType;
        }

        public static string GetMessageTypeNumber(MessageTypes messageType)
        {
            return Enum.Format(typeof(MessageTypes), messageType, "d").ToString();
        }

        public static string ConstructObjectXml(object content, Type contentType)
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(contentType);
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                System.IO.StringWriter sw = new System.IO.StringWriter(sb);
                System.Xml.XmlTextWriter tw = new System.Xml.XmlTextWriter(sw);

                // get rid of xml Processing Instruction declarations
                tw.Formatting = System.Xml.Formatting.None;
                tw.WriteRaw(String.Empty);

                // get rid of xsd/xsi declaraions
                //XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
                //xsn.Add(String.Empty, String.Empty);

                // serialize and return the result
                serializer.Serialize(tw, content);
                return sb.ToString();
            }
            catch (Exception exc)
            {
                int x = 2;
            }
            return "";
        }
    }
}
